package com.bestcem.xm.txtanls.grpc.client;

import cn.hutool.core.collection.CollUtil;
import com.bestcem.xm.bi.grpc.v1.services.*;
import com.bestcem.xm.common.core.constant.GrpcClientNames;
import com.bestcem.xm.txtanls.service.dto.worktable.ColumnDTO;
import com.bestcem.xm.txtanls.service.dto.worktable.DatasourceDTO;
import com.bestcem.xm.txtanls.service.dto.worktable.WorktableDTO;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import zhongyan.xm.base.v1.Base;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;


/**
 * 倍市得 BI 模块相关rpc接口客户端
 *
 * @author gy.liu
 * @version 1.0
 * @date 2021/6/10 17:01
 */
@Slf4j
@Service
public class BaseBiGrpcService {

    @GrpcClient(GrpcClientNames.XM)
    private BaseBiServiceGrpc.BaseBiServiceBlockingStub baseBiServiceBlockingStub;

    /**
     * 获取 datasource 信息
     *
     * @param datasourceId 数据源id
     * @return Datasource info
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/6/29 9:33
     */
    public DatasourceDTO getDataSource(String datasourceId) {
        GetDatasourceRequest.Builder builder = GetDatasourceRequest.newBuilder();
        builder.setId(datasourceId);
        try {
            DatasourceResponse response = baseBiServiceBlockingStub.getDatasource(builder.buildPartial());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Txtanls] BI getDataSource {} Error; ErrorMsg: {};", datasourceId, response);
                return null;
            }
            return responseToDatasourceDTO(response);
        } catch (Exception e) {
            log.error("[Txtanls] BI getDataSource {} Error; ErrorMsg: {};", datasourceId, e.getMessage(), e);
            return null;
        }
    }


    /**
     * 获取 worktable 信息
     *
     * @param worktableId worktableId
     * @return Worktable info
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/6/29 9:32
     */
    public WorktableDTO getWorktable(String worktableId) {
        GetWorktableRequest.Builder builder = GetWorktableRequest.newBuilder();
        builder.setId(worktableId);
        try {
            WorktableResponse response = baseBiServiceBlockingStub.getWorktable(builder.build());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Txtanls] BI getWorktable {} Error; ErrorMsg: {};", worktableId, response);
                return null;
            }
            return responseToWorktableDTO(response);
        } catch (Exception e) {
            log.error("[Txtanls] BI getWorktable {} Error; ErrorMsg: {};", worktableId, e.getMessage(), e);
            return null;
        }
    }


    /**
     * 根据orgId和userId获取数据源list
     *
     * @param orgId  组织id
     * @param userId 用户id
     * @date 2021/6/21 17:08
     * @author liheng
     */
    public List<WorktableDTO> listWorktableByOrgIdAndUserId(String orgId, String userId) {
        ListWorktableRequest.Builder builder = ListWorktableRequest.newBuilder();
        Worktable.Builder worktableBuilder = Worktable.newBuilder();
        worktableBuilder.setOrgId(orgId);
        worktableBuilder.setUserId(userId);
        worktableBuilder.setVisible(WorktableVisible.WORKTABLE_VISIBLE_VISIBLE);
        builder.setWorktable(worktableBuilder.build());
        try {
            WorktableSearchResponse response = baseBiServiceBlockingStub.listWorktable(builder.buildPartial());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Txtanls] BI listWorktableByOrgIdAndUserId {}-{} Error; ErrorMsg: {}", orgId, userId,
                        response);
                return null;
            }
            return responseToWorktableDTOList(response);
        } catch (Exception e) {
            log.error("[Txtanls] BI listWorktableByOrgIdAndUserId {}-{} Error; ErrorMsg: {}", orgId, userId,
                    e.getMessage(), e);
            return null;
        }
    }

    /**
     * 根据数据源id list获取数据源信息
     *
     * @author liheng
     * @date 2021/6/21 18:51
     */
    public List<WorktableDTO> listWorkTableByIds(List<String> workTableIds) {
        if (CollUtil.isEmpty(workTableIds)) {
            return Collections.emptyList();
        }
        ListWorktableByIdsRequest.Builder builder = ListWorktableByIdsRequest.newBuilder();
        builder.addAllIds(workTableIds);
        try {
            WorktableSearchResponse response = baseBiServiceBlockingStub.listWorktableByIds(builder.buildPartial());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Txtanls] BI listWorkTableByIds {} Error; ErrorMsg: {}", workTableIds, response);
                return null;
            }
            return responseToWorktableDTOList(response);
        } catch (Exception e) {
            log.error("[Txtanls] BI listWorkTableByIds {} Error; ErrorMsg: {}", workTableIds, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 获取数据源列信息
     *
     * @param columnId 列id
     * @return Column info
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/6/22 14:10
     */
    public ColumnDTO getColumn(String columnId) {
        GetColumnRequest.Builder builder = GetColumnRequest.newBuilder();
        builder.setId(columnId);
        try {
            ColumnResponse response = baseBiServiceBlockingStub.getColumn(builder.buildPartial());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Txtanls] BI getColumn {} Error; ErrorMsg: {}", columnId, response);
                return null;
            }
            return responseToColumnDTO(response);
        } catch (Exception e) {
            log.error("[Txtanls] BI getColumn {} Error; ErrorMsg: {}", columnId, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 根据数据源id和数据类型获取所有列的信息数组
     *
     * @param worktableId worktableId
     * @param dataType    列数据类型
     * @return Information about all columns to be queried
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/6/24 13:19
     */
    public List<ColumnDTO> listColumnByWorktableIdAndType(String worktableId, Integer dataType) {
        ListColumnRequest.Builder builder = ListColumnRequest.newBuilder();
        Column.Builder columnBuilder = Column.newBuilder();
        columnBuilder.setWorktableId(worktableId);
        columnBuilder.setDtype(ColumnDtype.forNumber(dataType));
        builder.setColumn(columnBuilder.buildPartial());
        try {
            ColumnSearchResponse response = baseBiServiceBlockingStub.listColumn(builder.buildPartial());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Txtanls] BI listColumnByWorktableIdAndType {}-{} Error; ErrorMsg: {}", worktableId, dataType, response);
                return null;
            }
            return responseToColumnDTOList(response);
        } catch (Exception e) {
            log.error("[Txtanls] BI listColumnByWorktableIdAndType {}-{} Error; ErrorMsg: {}", worktableId, dataType, e.getMessage(), e);
            return null;
        }
    }


    /**
     * 根据 worktableId 获取所有列的信息
     *
     * @param worktableId worktableId
     * @return Worktable all column
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/6/22 11:25
     */
    public List<ColumnDTO> listColumnByWorktableId(String worktableId) {
        ListColumnRequest.Builder builder = ListColumnRequest.newBuilder();
        Column.Builder columnBuilder = Column.newBuilder();
        columnBuilder.setWorktableId(worktableId);
        builder.setColumn(columnBuilder.buildPartial());
        try {
            ColumnSearchResponse response = baseBiServiceBlockingStub.listColumn(builder.buildPartial());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Txtanls] BI listColumnByWorktableId {} Error; ErrorMsg: {}", worktableId, response);
                return null;
            }
            return responseToColumnDTOList(response);
        } catch (Exception e) {
            log.error("[Txtanls] BI listColumnByWorktableId {} Error; ErrorMsg: {}", worktableId, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 根据 worktableId 获取对应显示类型的所有列的信息
     *
     * @param worktableId worktableId
     * @param isVisible   显示类型
     * @return Worktable all column
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/6/22 11:25
     */
    public List<ColumnDTO> listColumnByWorktableId(String worktableId, boolean isVisible) {
        ListColumnRequest.Builder builder = ListColumnRequest.newBuilder();
        Column.Builder columnBuilder = Column.newBuilder();
        columnBuilder.setWorktableId(worktableId);
        columnBuilder.setVisible(isVisible);
        builder.setColumn(columnBuilder.buildPartial());
        try {
            ColumnSearchResponse response = baseBiServiceBlockingStub.listColumn(builder.buildPartial());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Txtanls] BI listColumnByWorktableId {} Error; ErrorMsg: {}", worktableId, response);
                return null;
            }
            return responseToColumnDTOList(response);
        } catch (Exception e) {
            log.error("[Txtanls] BI listColumnByWorktableId {} Error; ErrorMsg: {}", worktableId, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 根据列id list查询列信息list
     *
     * @param columnIds 所有要查询的column的id集合
     * @return Information about all columns to be queried
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/6/24 13:12
     */
    public List<ColumnDTO> listColumnDTOByIds(List<String> columnIds) {
        if (CollUtil.isEmpty(columnIds)) {
            return Collections.emptyList();
        }
        ListColumnByIdsRequest.Builder builder = ListColumnByIdsRequest.newBuilder();
        builder.addAllIds(columnIds);
        try {
            ColumnSearchResponse response = baseBiServiceBlockingStub.listColumnByIds(builder.buildPartial());
            if (Base.Code.ERROR.equals(response.getStatus().getCode())) {
                throw new RuntimeException(response.getStatus().getMessage());
            }
            return responseToColumnDTOList(response);
        } catch (Exception e) {
            log.error("[Txtanls] BI listColumnDTOByIds {} Error; ErrorMsg: {}", columnIds, e.getMessage(), e);
            return null;
        }
    }


    // ========================== private model convert ==========================

    /**
     * WorktableResponse to WorktableDTO
     *
     * @param response WorktableResponse
     * @return WorktableDTO
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/8/2 14:40
     */
    private WorktableDTO responseToWorktableDTO(WorktableResponse response) {
        Worktable worktable = response.getWorktable();
        return infoToWorktableDTO(worktable);
    }

    /**
     * WorktableSearchResponse to List<WorktableDTO>
     *
     * @param response WorktableSearchResponse
     * @return List<WorktableDTO>
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/8/2 14:40
     */
    private List<WorktableDTO> responseToWorktableDTOList(WorktableSearchResponse response) {
        List<WorktableDTO> worktableDTOList = new ArrayList<>();
        List<Worktable> worktables = response.getWorktableListList();
        for (Worktable worktable : worktables) {
            worktableDTOList.add(infoToWorktableDTO(worktable));
        }
        return worktableDTOList;
    }

    /**
     * Worktable to WorktableDTO
     *
     * @param worktable Worktable
     * @return WorktableDTO
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/8/2 14:40
     */
    private WorktableDTO infoToWorktableDTO(Worktable worktable) {
        WorktableDTO worktableDTO = new WorktableDTO();
        worktableDTO.setId(worktable.getId());
        worktableDTO.setOrgId(worktable.getOrgId());
        worktableDTO.setUserId(worktable.getUserId());
        worktableDTO.setName(worktable.getName());
        worktableDTO.setDescription(worktable.getDescription());
        worktableDTO.setDatasourceId(worktable.getDatasourceId());
        worktableDTO.setEngine(worktable.getEngine().getNumber());
        worktableDTO.setStatus(worktable.getStatus().getNumber());
        worktableDTO.setType(worktable.getTtype().getNumber());
        worktableDTO.setVisible(worktable.getVisible().getNumber());
        worktableDTO.setCustomAttr(worktable.getCustomAttr());
        worktableDTO.setProjectIdList(worktable.getProjectIdList());
        worktableDTO.setDruidMappingId(worktable.getDruidMappingId());
        worktableDTO.setDruidVersion(worktable.getDruidVersion());
        worktableDTO.setCleanerList(worktable.getCleanersList());
        return worktableDTO;
    }

    /**
     * DatasourceResponse to DatasourceDTO
     *
     * @param response DatasourceResponse
     * @return DatasourceDTO
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/8/2 14:40
     */
    private DatasourceDTO responseToDatasourceDTO(DatasourceResponse response) {
        Datasource datasource = response.getDatasource();
        DatasourceDTO datasourceDTO = new DatasourceDTO();
        datasourceDTO.setId(datasource.getId());
        datasourceDTO.setOrgId(datasource.getOrgId());
        datasourceDTO.setName(datasource.getName());
        datasourceDTO.setFilename(datasource.getFilename());
        datasourceDTO.setCollection(datasource.getCollection());
        datasourceDTO.setCollectionFilter(datasource.getCollectionFilter());
        datasourceDTO.setSurveyId(datasource.getSurveyId());
        datasourceDTO.setSurveyCode(datasource.getSurveyCode());
        datasourceDTO.setSurveyVersion(datasource.getSurveyVersion());
        datasourceDTO.setDataMergeId(datasource.getDatamergeId());
        datasourceDTO.setQdesCid(datasource.getQdesCid());
        datasourceDTO.setRootGroupGd(datasource.getRootGroupId());
        datasourceDTO.setType(datasource.getTtypeValue());
        datasourceDTO.setReadData(datasource.getReadData());
        datasourceDTO.setTableName(datasource.getTableName());
        datasourceDTO.setDruidRelationId(datasource.getDruidRelationId());
        return datasourceDTO;
    }

    /**
     * ColumnResponse to ColumnDTO
     *
     * @param response ColumnResponse
     * @return ColumnDTO
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/8/2 14:40
     */
    private ColumnDTO responseToColumnDTO(ColumnResponse response) {
        Column column = response.getColumn();
        return infoToColumnDTO(column);
    }

    /**
     * ColumnSearchResponse to List<ColumnDTO>
     *
     * @param response ColumnSearchResponse
     * @return List<ColumnDTO>
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/8/2 14:40
     */
    private List<ColumnDTO> responseToColumnDTOList(ColumnSearchResponse response) {
        List<ColumnDTO> columnDTOList = new ArrayList<>();
        List<Column> columnList = response.getColumnListList();
        if (!CollectionUtils.isEmpty(columnList)) {
            for (Column column : columnList) {
                ColumnDTO columnDTO = infoToColumnDTO(column);
                if (Objects.nonNull(columnDTO)) {
                    columnDTOList.add(columnDTO);
                }
            }
        }
        return columnDTOList;
    }

    /**
     * Column to ColumnDTO
     *
     * @param column Column
     * @return ColumnDTO
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/8/2 14:40
     */
    private ColumnDTO infoToColumnDTO(Column column) {
        if (Objects.isNull(column)) {
            return null;
        }
        ColumnDTO columnDTO = new ColumnDTO();
        columnDTO.setId(column.getId());
        columnDTO.setOrgId(column.getOrgId());
        columnDTO.setCol(column.getCol());
        columnDTO.setRealCol(column.getRealcol());
        columnDTO.setTableCol(column.getTablecol());
        columnDTO.setBaseCol(column.getBasecol());
        columnDTO.setReadableCol(column.getReadablecol());
        columnDTO.setWorktableId(column.getWorktableId());
        columnDTO.setRawWorktableId(column.getRawWorktableId());
        columnDTO.setVisible(column.getVisible());
        columnDTO.setUsage(column.getUsageValue());
        columnDTO.setTType(column.getTtypeValue());
        columnDTO.setDType(column.getDtypeValue());
        columnDTO.setAType(column.getAtypeValue());
        columnDTO.setChartId(column.getChartId());
        columnDTO.setClassifyColumnType(column.getClassifyColumnTypeValue());
        columnDTO.setClassifyType(column.getClassifyTypeValue());
        columnDTO.setClassifyColumnId(column.getClassifyColumnId());
        columnDTO.setClassifyIdList(column.getClassifyIdListList());
        columnDTO.setClassifyOverType(column.getClassifyOverTypeValue());
        columnDTO.setClassifyOverName(column.getClassifyOverName());
        columnDTO.setExpression(column.getExpression());
        columnDTO.setExpressionColumnIdList(column.getExpressionColumnIdListList());
        columnDTO.setValueGroupIdList(column.getValueGroupIdListList());
        columnDTO.setCopedColumnId(column.getCopyedColumnId());
        columnDTO.setOriginalColumnIdList(column.getOriginalColumnIdListList());
        columnDTO.setAnalyseUsed(column.getAnalyseUsed());
        columnDTO.setBasedColumnIdList(column.getBasedColumnIdListList());
        columnDTO.setAggable(column.getAggable());
        columnDTO.setIsUnique(column.getIsUnique());
        columnDTO.setChange(column.getChange());
        columnDTO.setLocation(column.getLocation());
        columnDTO.setOrder(column.getOrder());
        columnDTO.setColumnConcatId(column.getColumnConcatId());
        return columnDTO;
    }
}
